<?php
/*
 * RBAC基于角色的访问控制接口
 * 
 * @author Leo
 * 
 */
/**
 * 
 * 资源管理器
 * @author LeoNing
 *
 */
class RbacResourceManager {
	public $resources = array ();
	/**
	 * 
	 * 添加一个资源
	 * @param RbacResource $resouce
	 */
	public function add($resouce) {
		$this->resources [$resouce->id] = $resouce;
	}
	/**
	 * 
	 * 获取一个资源,用于修改
	 * @param RbacResource $id
	 */
	public function get($id) {
		if (isset ( $this->resources [$id] )) {
			return $this->resources [$id];
		}
		return false;
	}
}
/**
 * 
 * 资源
 * @author LeoNing 
 *
 */
class RbacResource {
	public $id; //资源标识
	public $name; //资源名称
	public $ops = array (); //对资源的操作
	private $opts = array ('-1' => '继承', '0' => '禁止', '1' => '允许' );
	function __construct($id, $name) {
		$this->id = $id;
		$this->name = $name;
	}
	/**
	 * 
	 * 增加一个操作
	 * @param string $op 操作
	 * @param string $opname 操作名称
	 * @param boolean $extra 是否需要额外信息
	 */
	public function add($op, $opname, $extra = false) {
		$this->ops [$op] = array ('name' => $opname, 'extra' => $extra );
	}
	public function allowops($op, $privileges) {
		$key = $this->id . '.' . $op;
		$allow = - 1;
		if (isset ( $privileges [$key] )) {
			$allow = intval ( $privileges [$key] ['ALLOW'] );
		}
		$ops = array ();
		foreach ( $this->opts as $ks => $v ) {
			if ($ks === $allow) {
				$ops [] = '<option value="' . $ks . '" selected="selected">' . $v . '</option>';
			} else {
				$ops [] = '<option value="' . $ks . '">' . $v . '</option>';
			}
		}
		return implode ( '', $ops );
	}
	public function priority($op, $privileges) {
		$key = $this->id . '.' . $op;
		$priority = 0;
		if (isset ( $privileges [$key] )) {
			$priority = intval ( $privileges [$key] ['PRIORITY'] );
		}
		return $priority;
	}
	public function hasop($op, $privileges) {
		$key = $this->id . '.' . $op;
		return isset ( $privileges [$key] );
	}
	public function cname($id,$op, $privileges) {
		$key = $this->id . '.' . $id;
		$allow = - 1;
		if (isset ( $privileges [$key] )) {
			$allow = intval ( $privileges [$key] ['ALLOW'] );
		}
		if ($allow == 0) {
			return '<span class="tred">' . $op ['name'] . '</span>';
		} else if ($allow == 1) {
			return '<span class="tgre">' . $op ['name'] . '</span>';
		}
		return $op ['name'];
	}
}

interface IRbac {
	/**
	 * 为访问者分配权限
	 * @param array $ops 权限
	 * @param string $resource 资源
	 * @param mixed $id 访问者标识,建议使用int或string型,长度不应长于32
	 * @param mixed $type 访问者类型,可自定义
	 * @param int $priority 优先级
	 * @param array $extra 额外信息	 
	 * @return boolean 
	 */
	function grant($ops, $resource, $id, $type, $priority = 0, $extra = array());
	/**
	 * 
	 * 得到权限分配记录的额外信息
	 * @param string $op
	 * @param string $resource
	 * @param mixed $id
	 * @param string $type
	 */
	function getextra($op, $resource, $id, $type);
	/**
	 * 
	 * 为权限分配额外信息
	 * @param string $op 操作
	 * @param string $resource 资源
	 * @param mixed $id
	 * @param string $type
	 * @param array $extra 额外信息
	 * @return boolean
	 */
	function setextra($op, $resource, $id, $type, $extra);
	/**
	 * 收回访问者权限
	 * @param array $ops 要收回的权限
	 * @param string $resource
	 * @param mixed $id 访问者标识,建议使用int或string型,长度不应长于32
	 * @param mixed $type 访问者类型,可自定义
	 * @return boolean 
	 */
	function revoke($ops, $resource, $id, $type);
	/**
	 * 
	 * 收回访问者所有权限
	 * @param mixed $id 访问者标识,建议使用int或string型,长度不应长于32
	 * @param mixed $type 访问者类型,可自定义
	 * @return boolean
	 */
	function revokeAll($id, $type);
	/**
	 * Can I do some operation on resource? If I can return true, else return false
	 * 
	 * @param string $op 操作
	 * @param string $resource 资源
	 * @param mixed $id 访问者标识,建议使用int或string型,长度不应长于32
	 * @return mixed 无权操作时返回false,反之返回extra信息
	 */
	function icando($op, $resource, $id);
	/**
	 * 权限分配表
	 * 
	 * @param mixed $id 访问者标识,建议使用int或string型,长度不应长于32
	 * @param array $types 访问者类型,可自定义
	 * @return array 权限分配表
	 */
	function privileges($id, $types);
}
/**
 * Can I do some operation on resource? If I can return true, else return false
 * 
 * @param string $op 操作
 * @param string $resource 资源
 * @return mixed 无权操作时返回false,反之返回extra信息
 */
function icando($op, $resource) {
	$I = whoami ();
	return ucando ( $op, $resource, $I->id );
}
/**
 * Can you/she/he do some operation on resource? If I can return true, else return false
 * 
 * @param string $op 操作
 * @param string $resource 资源
 * @param mixed $id 访问者标识,建议使用int或string型,长度不应长于32	
 * @return mixed 无权操作时返回false,反之返回extra信息
 */
function ucando($op, $resource, $id) {
	global $__rbac;
	if ($__rbac == null) {
		$ioc = get_current_ioc ();
		$__rbac = $ioc->get ( 'rbac' );
	}
	if ($__rbac && method_exists ( $__rbac, 'icando' )) {
		return $__rbac->icando ( $op, $resource, $id );
	}
	return false;
}